#!/usr/bin/env python3
"""
邮箱账号管理路由
提供邮箱账号的CRUD操作以及相关功能
"""

from flask import Blueprint, request, jsonify
from flask_jwt_extended import jwt_required, get_jwt_identity
from datetime import datetime, timedelta
import time
import logging
import smtplib
import threading

from models import db, EmailAccount, EmailMessage
from utils.email_helpers import generate_email_account_id, imap_utf7_decode, normalize_folder_name
from utils.encryption import email_encryption
from utils.imap_pool import imap_connection_pool
from services.email_service import EmailService

email_logger = logging.getLogger('email_system')

# 创建蓝图
accounts_bp = Blueprint('email_accounts', __name__)


@accounts_bp.route('/', methods=['GET'])
@jwt_required()
def get_email_accounts():
    """获取当前用户的所有邮箱配置"""
    try:
        current_user_id = int(get_jwt_identity())
        accounts = EmailAccount.query.filter_by(user_id=current_user_id).order_by(EmailAccount.created_at.desc()).all()
        
        return jsonify({
            'accounts': [account.to_dict() for account in accounts]
        }), 200
        
    except Exception as e:
        return jsonify({'error': str(e)}), 500


@accounts_bp.route('/', methods=['POST'])
@jwt_required()
def create_email_account():
    """创建新邮箱配置"""
    try:
        current_user_id = int(get_jwt_identity())
        data = request.get_json()
        
        # 验证必填字段
        required_fields = ['name', 'email', 'smtp_server', 'smtp_port', 'imap_server', 'imap_port', 'username', 'password']
        for field in required_fields:
            if not data or not data.get(field):
                return jsonify({'error': f'{field} 不能为空'}), 400
        
        # 加密密码
        encrypted_password = email_encryption.encrypt_password(data['password'])
        
        # 创建邮箱账号
        account = EmailAccount(
            id=generate_email_account_id(),
            user_id=current_user_id,
            name=data['name'],
            email=data['email'],
            smtp_server=data['smtp_server'],
            smtp_port=int(data['smtp_port']),
            imap_server=data['imap_server'],
            imap_port=int(data['imap_port']),
            username=data['username'],
            password=encrypted_password,
            use_ssl=data.get('use_ssl', True),
            is_default=data.get('is_default', False),
            description=data.get('description', '')
        )
        
        # 如果设置为默认邮箱，取消其他邮箱的默认状态
        if account.is_default:
            EmailAccount.query.filter_by(user_id=current_user_id, is_default=True).update({'is_default': False})
        
        db.session.add(account)
        db.session.commit()
        
        return jsonify({
            'success': True,
            'account': account.to_dict()
        }), 201
        
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': str(e)}), 500


@accounts_bp.route('/<account_id>', methods=['GET'])
@jwt_required()
def get_email_account(account_id):
    """获取单个邮箱配置"""
    try:
        current_user_id = int(get_jwt_identity())
        account = EmailAccount.query.filter_by(id=account_id, user_id=current_user_id).first()
        
        if not account:
            return jsonify({'error': '邮箱配置不存在'}), 404
        
        return jsonify({
            'account': account.to_dict()
        }), 200
        
    except Exception as e:
        return jsonify({'error': str(e)}), 500


@accounts_bp.route('/<account_id>', methods=['PUT'])
@jwt_required()
def update_email_account(account_id):
    """更新邮箱配置"""
    try:
        current_user_id = int(get_jwt_identity())
        account = EmailAccount.query.filter_by(id=account_id, user_id=current_user_id).first()
        
        if not account:
            return jsonify({'error': '邮箱配置不存在'}), 404
        
        data = request.get_json()
        
        # 更新字段
        if 'name' in data:
            account.name = data['name']
        if 'email' in data:
            account.email = data['email']
        if 'smtp_server' in data:
            account.smtp_server = data['smtp_server']
        if 'smtp_port' in data:
            account.smtp_port = int(data['smtp_port'])
        if 'imap_server' in data:
            account.imap_server = data['imap_server']
        if 'imap_port' in data:
            account.imap_port = int(data['imap_port'])
        if 'username' in data:
            account.username = data['username']
        if 'password' in data and data['password']:
            account.password = email_encryption.encrypt_password(data['password'])
        if 'use_ssl' in data:
            account.use_ssl = data['use_ssl']
        if 'is_default' in data:
            account.is_default = data['is_default']
            # 如果设置为默认邮箱，取消其他邮箱的默认状态
            if account.is_default:
                EmailAccount.query.filter_by(user_id=current_user_id, is_default=True).filter(EmailAccount.id != account_id).update({'is_default': False})
        if 'description' in data:
            account.description = data['description']
        
        db.session.commit()
        
        return jsonify({
            'success': True,
            'account': account.to_dict()
        }), 200
        
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': str(e)}), 500


@accounts_bp.route('/<account_id>', methods=['DELETE'])
@jwt_required()
def delete_email_account(account_id):
    """删除邮箱配置"""
    try:
        current_user_id = int(get_jwt_identity())
        account = EmailAccount.query.filter_by(id=account_id, user_id=current_user_id).first()
        
        if not account:
            return jsonify({'error': '邮箱配置不存在'}), 404
        
        db.session.delete(account)
        db.session.commit()
        
        return jsonify({
            'success': True,
            'message': '邮箱配置已删除'
        }), 200
        
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': str(e)}), 500


@accounts_bp.route('/<account_id>/test', methods=['POST'])
@jwt_required()
def test_email_account(account_id):
    """测试邮箱连接"""
    try:
        current_user_id = int(get_jwt_identity())
        account = EmailAccount.query.filter_by(id=account_id, user_id=current_user_id).first()
        
        if not account:
            return jsonify({'error': '邮箱配置不存在'}), 404
        
        # 解密密码
        password = email_encryption.decrypt_password(account.password)
        
        # 测试SMTP连接
        try:
            # QQ邮箱端口587使用STARTTLS，端口465使用SSL
            if account.smtp_port == 465:
                # 端口465使用SSL
                smtp_server = smtplib.SMTP_SSL(account.smtp_server, account.smtp_port)
            else:
                # 端口587使用STARTTLS
                smtp_server = smtplib.SMTP(account.smtp_server, account.smtp_port)
                smtp_server.starttls()
            
            smtp_server.login(account.username, password)
            smtp_server.quit()
            
            return jsonify({
                'success': True,
                'message': 'SMTP连接测试成功'
            }), 200
            
        except Exception as e:
            return jsonify({
                'success': False,
                'error': f'SMTP连接测试失败: {str(e)}'
            }), 400
        
    except Exception as e:
        return jsonify({'error': str(e)}), 500


@accounts_bp.route('/<account_id>/stats', methods=['GET'])
@jwt_required()
def get_email_stats(account_id):
    """获取邮箱的邮件统计信息"""
    try:
        current_user_id = int(get_jwt_identity())
        account = EmailAccount.query.filter_by(id=account_id, user_id=current_user_id).first()
        if not account:
            return jsonify({'error': '邮箱账号不存在'}), 404
        
        # 获取数据库中的邮件数量
        db_message_count = EmailMessage.query.filter_by(email_account_id=account_id).count()
        
        # 获取各文件夹的邮件数量
        folder_stats = {}
        folders = EmailMessage.query.filter_by(email_account_id=account_id).with_entities(
            EmailMessage.folder, db.func.count(EmailMessage.id)
        ).group_by(EmailMessage.folder).all()
        
        for folder, count in folders:
            folder_stats[folder] = count
        
        # 获取邮箱总邮件数量（需要连接IMAP）
        total_message_count = 0
        try:
            with imap_connection_pool.get_connection(account) as mail:
                # 获取所有文件夹
                status, folders = mail.list()
                if status == 'OK':
                    for folder in folders:
                        folder_str = folder.decode('utf-8')
                        try:
                            # 解析IMAP文件夹格式
                            parts = folder_str.split('"')
                            if len(parts) >= 3:
                                imap_folder_name = parts[-2]
                            else:
                                imap_folder_name = folder_str.split()[-1]
                            
                            # 跳过空文件夹名或特殊编码文件夹
                            if not imap_folder_name.strip():
                                continue
                            
                            # 使用readonly模式选择文件夹
                            status, select_data = mail.select(imap_folder_name, readonly=True)
                            if status == 'OK':
                                status, messages = mail.search(None, 'ALL')
                                if status == 'OK' and messages[0]:
                                    folder_count = len(messages[0].split())
                                    total_message_count += folder_count
                        except Exception as e:
                            # 静默跳过无法访问的文件夹（如只写文件夹、特殊编码文件夹等）
                            email_logger.debug(f"[统计] 跳过文件夹 {imap_folder_name}: {e}")
                            continue
        except Exception as e:
            email_logger.warning(f"[统计] 无法连接IMAP获取总邮件数: {e}")
        
        return jsonify({
            'success': True,
            'account_id': account_id,
            'account_email': account.email,
            'db_message_count': db_message_count,
            'total_message_count': total_message_count,
            'folder_stats': folder_stats,
            'is_first_fetch': account.is_first_fetch,
            'last_fetch_at': account.last_fetch_at.isoformat() if account.last_fetch_at else None,
            'is_fetching': account.is_fetching
        }), 200
        
    except Exception as e:
        email_logger.error(f"[邮件统计] 错误: {e}")
        return jsonify({'error': '获取邮件统计失败'}), 500


@accounts_bp.route('/<account_id>/clear', methods=['POST'])
@jwt_required()
def clear_emails(account_id):
    """清空指定邮箱账号下的所有邮件"""
    try:
        current_user_id = int(get_jwt_identity())
        account = EmailAccount.query.filter_by(id=account_id, user_id=current_user_id).first()
        
        if not account:
            return jsonify({'error': '邮箱配置不存在'}), 404
        
        # 删除该账号下的所有邮件
        deleted_count = EmailMessage.query.filter_by(
            user_id=current_user_id, 
            email_account_id=account_id
        ).delete()
        
        # 重置首次拉取标志和拉取状态
        account.is_first_fetch = True
        account.last_sync_uid = None
        account.is_fetching = False  # 重置拉取锁
        account.last_fetch_at = None  # 重置最后拉取时间
        
        db.session.commit()
        
        return jsonify({
            'success': True,
            'message': f'已清空 {deleted_count} 封邮件'
        }), 200
        
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': str(e)}), 500


@accounts_bp.route('/<account_id>/fetch', methods=['POST'])
@jwt_required()
def fetch_emails(account_id):
    """从服务器拉取邮件 - 支持后台任务"""
    try:
        current_user_id = int(get_jwt_identity())
        account = EmailAccount.query.filter_by(id=account_id, user_id=current_user_id).first()
        
        if not account:
            return jsonify({'error': '邮箱配置不存在'}), 404
        
        # 检查是否正在拉取 + 超时保护
        if account.is_fetching:
            # 检查是否超时（15分钟）
            if account.last_fetch_at and \
               datetime.utcnow() - account.last_fetch_at < timedelta(minutes=15):
                return jsonify({
                    'success': False, 
                    'error': '正在拉取中，请稍后再试',
                    'is_fetching': True
                }), 409
            else:
                # 超时了，强制解锁
                email_logger.warning(f"[邮件拉取] 检测到超时锁，强制解除: {account.email}")
                account.is_fetching = False
                db.session.commit()
        
        # 启动后台拉取任务
        task = threading.Thread(target=EmailService.fetch_emails_for_account, args=(account_id,))
        task.daemon = True
        task.start()
        
        return jsonify({
            'success': True,
            'message': '后台拉取已启动',
            'task_id': account_id,
            'is_fetching': True
        }), 202
        
    except Exception as e:
        return jsonify({'error': str(e)}), 500


@accounts_bp.route('/<account_id>/fetch-status', methods=['GET'])
@jwt_required()
def fetch_status(account_id):
    """获取邮件拉取状态"""
    try:
        current_user_id = int(get_jwt_identity())
        account = EmailAccount.query.filter_by(id=account_id, user_id=current_user_id).first()
        
        if not account:
            return jsonify({'error': '邮箱配置不存在'}), 404
        
        return jsonify({
            'is_fetching': account.is_fetching,
            'last_fetch_at': account.last_fetch_at.isoformat() if account.last_fetch_at else None,
            'last_sync_uid': account.last_sync_uid
        }), 200
        
    except Exception as e:
        return jsonify({'error': str(e)}), 500


@accounts_bp.route('/<account_id>/unlock', methods=['POST'])
@jwt_required()
def unlock_fetching(account_id):
    """强制解锁邮件拉取状态（管理员用）"""
    try:
        current_user_id = int(get_jwt_identity())
        account = EmailAccount.query.filter_by(id=account_id, user_id=current_user_id).first()
        
        if not account:
            return jsonify({'error': '邮箱配置不存在'}), 404
        
        if account.is_fetching:
            account.is_fetching = False
            db.session.commit()
            email_logger.info(f"[邮件拉取] 手动解锁成功 - 账号: {account.email}")
            return jsonify({
                'success': True,
                'message': '拉取状态已解锁'
            }), 200
        else:
            return jsonify({
                'success': True,
                'message': '账号未处于拉取状态'
            }), 200
        
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': str(e)}), 500


@accounts_bp.route('/<account_id>/folders', methods=['GET'])
@jwt_required()
def get_email_folders(account_id):
    """获取邮箱文件夹列表"""
    try:
        current_user_id = int(get_jwt_identity())
        account = EmailAccount.query.filter_by(id=account_id, user_id=current_user_id).first()
        
        if not account:
            return jsonify({'error': '邮箱配置不存在'}), 404
        
        email_logger.info(f"[文件夹] 开始获取文件夹列表 - 账号: {account.email}")
        
        # 使用连接池获取连接
        with imap_connection_pool.get_connection(account) as mail:
            # 获取所有文件夹
            list_start_time = time.time()
            status, folders = mail.list()
            list_duration = time.time() - list_start_time
            
            if status != 'OK':
                email_logger.error(f"[文件夹] 获取文件夹列表失败 - 状态: {status}")
                return jsonify({'error': '获取文件夹列表失败'}), 500
            
            email_logger.info(f"[文件夹] 获取文件夹列表成功 - 耗时: {list_duration:.2f}秒, 数量: {len(folders)}")
            
            folder_list = []
            folder_map = {}  # 存储原始IMAP名称和显示名称的映射
            
            for folder in folders:
                folder_str = folder.decode('utf-8')
                try:
                    # 解析IMAP文件夹格式
                    parts = folder_str.split('"')
                    if len(parts) >= 3:
                        imap_folder_name = parts[-2]  # 获取最后一个引号内的内容（原始IMAP名称）
                    else:
                        imap_folder_name = folder_str.split()[-1]
                    
                    # 使用UTF-7解码得到显示名称
                    display_name = imap_utf7_decode(imap_folder_name)
                    
                    # 跳过空文件夹名
                    if not display_name.strip():
                        continue
                    
                    # 获取文件夹中的邮件数量（使用原始IMAP名称）
                    try:
                        select_status, count = mail.select(imap_folder_name, readonly=True)
                        if select_status == 'OK':
                            email_count = int(count[0].decode()) if count[0] else 0
                        else:
                            email_count = 0
                    except:
                        email_count = 0
                    
                    # 使用辅助函数标准化文件夹名称
                    normalized_name = normalize_folder_name(display_name)
                    
                    # 设置中文显示名称（仅用于展示）
                    # 如果是子文件夹（包含路径），只显示最后一段
                    if '/' in display_name:
                        display_name_cn = display_name.split('/')[-1]
                    else:
                        display_name_cn = display_name
                    
                    # 系统文件夹使用中文名
                    if normalized_name == 'inbox':
                        display_name_cn = '收件箱'
                    elif normalized_name == 'sent':
                        display_name_cn = '已发送'
                    elif normalized_name == 'drafts':
                        display_name_cn = '草稿箱'
                    elif normalized_name == 'trash':
                        display_name_cn = '垃圾箱'
                    elif normalized_name == 'junk':
                        display_name_cn = '垃圾邮件'
                    
                    folder_info = {
                        'name': display_name_cn,  # 中文显示名称
                        'normalized_name': normalized_name,  # 标准化英文名(用于查询)
                        'imap_name': imap_folder_name,  # 原始IMAP名称(用于IMAP操作)
                        'email_count': email_count,
                        'is_system': normalized_name in ['inbox', 'sent', 'drafts', 'trash', 'junk']
                    }
                    
                    folder_list.append(folder_info)
                    folder_map[imap_folder_name] = display_name
                    
                except Exception as e:
                    email_logger.warning(f"[文件夹] 解析文件夹名称失败: {folder_str}, 错误: {e}")
                    continue
            
            # 按系统文件夹优先，然后按名称排序
            system_folders = ['inbox', 'sent', 'drafts', 'trash', 'junk']
            folder_list.sort(key=lambda x: (
                0 if x['normalized_name'] in system_folders else 1,
                system_folders.index(x['normalized_name']) if x['normalized_name'] in system_folders else 999,
                x['name']
            ))
            
            email_logger.info(f"[文件夹] 返回文件夹列表 - 数量: {len(folder_list)}")
            
            # 创建display_name到normalized_name的映射
            display_to_normalized = {}
            for folder in folder_list:
                display_to_normalized[folder['name']] = folder['normalized_name']
            
            return jsonify({
                'folders': folder_list,
                'folder_map': folder_map,
                'display_to_normalized': display_to_normalized
            }), 200
        
    except Exception as e:
        email_logger.error(f"[文件夹] 获取文件夹列表异常 - 账号: {account.email}, 错误: {e}")
        return jsonify({'error': f'获取文件夹列表失败: {str(e)}'}), 500

